import { throttle } from 'lodash';
import * as THREE from 'three';
import Resize from '../utils/Resize';

export default async function (container: HTMLElement, imgPath: string, depthImgPath: string) {
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000);

  camera.position.set(0, 0, 6);

  let renderer = new THREE.WebGLRenderer({ antialias: true }),
    running = true;

  renderer.setSize(window.innerWidth, window.innerHeight);

  container.appendChild(renderer.domElement);

  // 纹理
  const textureLoader = new THREE.TextureLoader();
  const texture = await textureLoader.loadAsync(imgPath);
  const depthTexture = await textureLoader.loadAsync(depthImgPath);
  // 平面
  const geometry = new THREE.PlaneGeometry(25.6, 14.4);
  // 鼠标
  const mouse = new THREE.Vector2();

  // 材质
  const material = new THREE.ShaderMaterial({
    uniforms: {
      uTexture: { value: texture },
      uDepthTexture: { value: depthTexture },
      uMouse: { value: mouse },
    },
    vertexShader: `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }`,
    fragmentShader: `
    uniform sampler2D uTexture;
    uniform sampler2D uDepthTexture;
    uniform vec2 uMouse;
    varying vec2 vUv;
    void main() {
      vec4 color = texture2D(uTexture, vUv);
      vec4 depth = texture2D(uDepthTexture, vUv);
      float depthValue = depth.r;
      float x = vUv.x - uMouse.x * 0.005 * depthValue;
      float y = vUv.y + uMouse.y * 0.005 * depthValue;
      vec4 newColor = texture2D(uTexture, vec2(x, y));
      gl_FragColor = newColor;
    }
    `,
  });
  const plane = new THREE.Mesh(geometry, material);
  scene.add(plane);

  requestAnimationFrame(function animate() {
    if (!running) return;
    material.uniforms.uMouse.value = mouse;
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
  });

  window.addEventListener(
    'mousemove',
    throttle((e: MouseEvent) => {
      if (!running) return;
      mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
      mouse.y = (e.clientY / window.innerHeight) * 2 - 1;
    }, 16),
  );

  window.addEventListener('resize', () => {
    Resize(camera, renderer);
  });

  function SwitchListen(choose = false) {
    running = choose;
  }

  return {
    SwitchListen,
  };
}
